package com.youlei.newgraduateproject.controller;


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlei.newgraduateproject.common.easyexcel.converter.SysOrdersListener;
import com.youlei.newgraduateproject.entity.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author youlei
 * @since 2021-05-26
 */
@RestController
@RequestMapping("/sys/orders")
public class SysOrdersController extends BaseController {


    /**
     * @Author youlei
     * @Description 根据orderId查询单条订单信息
     * @Date 19:49 2021/5/28
     * @Param: [orderId]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @GetMapping("/info/{orderId}")
    @PreAuthorize("hasAuthority('sys:orders:list')")
    public CommonResult info(@PathVariable("orderId") Long orderId) {

        SysOrders sysOrder = sysOrdersService.getById(orderId);
        List<Long> orderitemsIds = getOrderitemIdsByOrderId(orderId);
        sysOrder.setOrderitemsIds(orderitemsIds);
        //断言，判断查询结果是否为空，若为空则抛出异常，可以在全局异常处理中处理
        Assert.notNull(sysOrder, "没有查询该订单数据,可能已经不存在");
        return new CommonResult(sysOrder);
    }


    /**
     * @Author youlei
     * @Description 查询所有订单信息（包括模糊查询）
     * @Date 12:10 2021/5/27
     * @Param: [orderNum]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @GetMapping("/list")
    //@PreAuthorize("hasAuthority('sys:orders:list')")
    public CommonResult list(String orderNum) {

        Page<SysOrders> pageData = sysOrdersService.page(getPage(), new QueryWrapper<SysOrders>()
                .like(StrUtil.isNotBlank(orderNum), "order_num", orderNum));
        return new CommonResult(pageData);
    }

    /**
     * @Author youlei
     * @Description 根据订单id通过中间表查询其订单项
     * @Date 20:04 2021/5/27
     * @Param: [orderId]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @GetMapping("/listOrderitemsById/{orderId}")
    @PreAuthorize("hasAuthority('sys:orders:list')")
    public CommonResult listOrderitemsByOrderId(@PathVariable("orderId") Long orderId) {

        //SysOrders sysOrder = sysOrdersService.getById(orderId);
        List<Long> orderitemIds = getOrderitemIdsByOrderId(orderId);
        List<SysOrderitem> sysOrderitems =new ArrayList<>();
        if(orderitemIds.size() > 0){

            //根据orderitemIds查询orderitem
             sysOrderitems = sysOrderitemService.listByIds(orderitemIds);
            for (SysOrderitem orderitem : sysOrderitems) {

                SysGoods good = sysGoodsService.getOne(new QueryWrapper<SysGoods>().eq("good_id", orderitem.getGoodId()).select("good_name"));
                orderitem.setGoodName(good.getGoodName());
            }

        }
        return new CommonResult(sysOrderitems);

    }


    /**
     * @Author youlei
     * @Description 修改订单信息
     * @Date 19:20 2021/5/31
     * @Param: [sysOrder]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @PostMapping("/update")
    @Transactional
    @PreAuthorize("hasAuthority('sys:orders:update')")
    public CommonResult update(@Validated @RequestBody SysOrders sysOrder) {
        
        sysOrdersService.update(sysOrder,new QueryWrapper<SysOrders>().eq("order_id",sysOrder.getOrderId()));
        //修改中间表
        //先删除中间表
        sysOrdersOrderitemService.remove(new QueryWrapper<SysOrdersOrderitem>().eq("order_id",sysOrder.getOrderId()));
        //再添加中间表,向订单和订单项的中间表中添加订单的关联数据
        List<Long> orderitemsIds = sysOrder.getOrderitemsIds();
        List<SysOrdersOrderitem> sysOrdersOrderitems = new ArrayList<>();
        for (int i=0;i<orderitemsIds.size();i++ ) {
            SysOrdersOrderitem sysOrdersOrderitem = new SysOrdersOrderitem();
            sysOrdersOrderitem.setOrderId(sysOrder.getOrderId());
            sysOrdersOrderitem.setOrderitemId(orderitemsIds.get(i));
            sysOrdersOrderitems.add(sysOrdersOrderitem);
        }
        sysOrdersOrderitemService.saveBatch(sysOrdersOrderitems);
        return new CommonResult(sysOrder);
    }
    /**
     * @Author youlei
     * @Description 新建一条订单数据
     * @Date 19:32 2021/5/31
     * @Param: [sysOrder, principal]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @PostMapping("/save")
    @Transactional
    @PreAuthorize("hasAuthority('sys:orders:save')")
    public CommonResult save(@Validated @RequestBody SysOrders sysOrder, Principal principal) {


        List<Long> orderitemsIds = sysOrder.getOrderitemsIds();
        List<SysOrdersOrderitem> sysOrdersOrderitems = new ArrayList<>();


        //查询订单的全部订单项的总金额
        Long[] ids = orderitemsIds.toArray(new Long[orderitemsIds.size()]);
        SysOrderitem sysOrderitem = sysOrderitemService
                .getOne(new QueryWrapper<SysOrderitem>()
                        .in("orderitem_id", ids)
                        .select("sum(total_price) as sumTotalPrice"));
        sysOrder.setOrderTotalmoney(sysOrderitem.getSumTotalPrice());
        sysOrder.setOrderNum(IdUtil.simpleUUID());
        sysOrder.setOrderCreater(principal.getName());
        sysOrder.setStatu(0);
        sysOrdersService.save(sysOrder);



        for (int i=0;i<orderitemsIds.size();i++ ) {
            SysOrdersOrderitem sysOrdersOrderitem = new SysOrdersOrderitem();
            sysOrdersOrderitem.setOrderId(sysOrder.getOrderId());
            sysOrdersOrderitem.setOrderitemId(orderitemsIds.get(i));
            sysOrdersOrderitems.add(sysOrdersOrderitem);
        }


        //向订单和订单项的中间表中添加订单的关联数据
        sysOrdersOrderitemService.saveBatch(sysOrdersOrderitems);


        return new CommonResult(200,"插入订单成功",sysOrder);
    }

    /**
     * @Author youlei
     * @Description 删除订单信息以及订单与订单项中间表的信息
     * @Date 23:18 2021/6/1
     * @Param: [orderIds]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @Transactional
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:orders:delete')")
    public CommonResult delete(@RequestBody Long[] orderIds) {

        sysOrdersService.removeByIds(Arrays.asList(orderIds));
        sysOrdersOrderitemService.remove(new QueryWrapper<SysOrdersOrderitem>().in("order_id", orderIds));

        return new CommonResult("");
    }


    /**
     * @Author youlei
     * @Description 订单确认功能
     * @Date 0:53 2021/6/2
     **/
    @PostMapping("/end")
    @Transactional
    @PreAuthorize("hasAuthority('sys:orders:end')")
    public CommonResult confirm(@RequestBody Long[] orderIds, Principal principal) {


        sysOrdersService.update(new UpdateWrapper<SysOrders>()
                .in("order_id",Arrays.asList(orderIds))
                .set("order_ender",principal.getName())
                .set("statu",3)
                .set("order_endtime", LocalDateTime.now()));

        return new CommonResult(200,"订单结束成功");
    }


    /**
     * @Author youlei
     * @Description 订单审核功能
     * @Date 0:52 2021/6/2
     * @Param: [sysOrder, principal]
     * @return: com.youlei.newgraduateproject.entity.CommonResult
     **/
    @PostMapping("/check")
    @Transactional
    @PreAuthorize("hasAuthority('sys:orders:check')")
    public CommonResult check(@RequestBody Long[] orderIds, Principal principal) {

        sysOrdersService.update(new UpdateWrapper<SysOrders>()
                .in("order_id",Arrays.asList(orderIds))
                .set("order_checker",principal.getName())
                .set("statu",1)
                .set("order_checkedtime",LocalDateTime.now()));

        return new CommonResult(200,"订单审核成功");
    }


    private List<SysOrders> data() {
        List<SysOrders> list = new ArrayList<SysOrders>();
        List<SysOrders> sysOrders = sysOrdersService.list();
        for (SysOrders order:sysOrders) {
            SysOrders data = new SysOrders();
            data.setOrderNum(order.getOrderNum());
            data.setOrderCreater(order.getOrderCreater());
            data.setOrderChecker(order.getOrderChecker());
            data.setOrderConfirmer(order.getOrderConfirmer());
            data.setOrderEnder(order.getOrderEnder());
            data.setCreated(order.getCreated());
            data.setOrderCheckedtime(order.getOrderCheckedtime());
            data.setOrderConfirmtime(order.getOrderConfirmtime());
            data.setOrderEndtime(order.getOrderEndtime());
            Long customerId = order.getOrderCustomerid();
            if(customerId!=null){
                data.setOrderCustomerName(getCustomerNameByCustomerId(customerId));
            }
            data.setOrderTotalmoney(order.getOrderTotalmoney());
            data.setRemark(order.getRemark());
            data.setOrderitemsIds(getOrderitemIdsByOrderId(order.getOrderId()));
            data.setStatu(order.getStatu());
            list.add(data);
            }

        return list;
    }
    /**
     * @Author youlei
     * @Description 文件下载并且失败的时候返回json（默认失败了会返回一个有部分数据的Excel）
     * @Date 22:33 2021/5/22
     * @Param: [response]
     * @return: void
     **/
    @GetMapping("/downloadOrdersExcel")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("所有订单信息", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            response.setHeader("FileName", fileName+".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), SysOrders.class)
                    .autoCloseStream(Boolean.FALSE)
                    //自动列宽
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("订单Excel表")
                    .doWrite(data());
        }
        catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
            System.out.println(e.getMessage());
        }
    }

    /**
     * 文件上传
     * 1. 创建excel对应的实体对象
     * 2. 由于默认一行行的读取excel，所以需要创建excel一行一行的回调监听器
     * 3. 直接读即可
     */
    @PostMapping(value = "/uploadOrdersExcel")
    @ResponseBody
    public CommonResult upload(@RequestParam("file") MultipartFile file) throws IOException {

            EasyExcel.read(file.getInputStream(), SysOrders.class, new SysOrdersListener(sysOrdersService)).sheet().doRead();

        return new CommonResult(200,"Excel数据批量导入成功");
    }

}
